package com.up.mongo.core;

import org.bson.json.JsonWriterSettings;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.List;

/**
 * mongo基础api
 * @param <E>
 * @param <ID>
 */
public interface IBaseMongoRepository<E, ID> {
    /**
     * 保存一个对象到mongodb
     *
     * @param entity 保存的实体对象
     * @return 返回保存后的实体
     */
    E save(E entity);

    /**
     * 保存多个对象到MongoDB
     * @param list 需要保存的实体组成的集合
     */
    void batchSave(List<E> list);

    /**
     * 根据id删除对象
     *
     * @param id ID
     */
    void deleteById(ID id);


    void deleteByQuery(Query query);

    /**
     * 根据对象的属性删除
     *
     * @param t 根据实体对象删除文档
     */
    void deleteByCondition(E t);


    /**
     * 根据id进行更新
     *
     * @param id ID
     * @param t  需要更新的实体对象
     */
    void updateById(ID id, E t);

    /**
     * 根据id进行更新
     * @param id
     * @param t
     * @param updateAll 是否全量更新
     */
    void updateById(ID id, E t,boolean updateAll);
    void upsert(Query query, Update update);

    /**
     * 根据id进行更新
     * @param id
     * @param update
     */
    void updateById(ID id,Update update);


    /**
     * 根据对象的属性查询
     *
     * @param t 实体对象
     * @return 返回符合实体查询条件得对象
     */
    List<E> findByCondition(E t);
    List<E> findByCondition(E t, String collectionName);


    /**
     * 通过条件查询实体(集合)
     *
     * @param query 查询Query对象
     */
    List<E> find(Query query);
    List<E> find(Query query, String collectionName);

    /**
     * 通过一定的条件查询一个实体
     *
     * @param query 查询Query对象
     * @return 查询Query对象
     */
    E findOne(Query query);

    /**
     * 通过一定的条件查询一个实体
     *
     * @param t 查询的实体对象
     * @return 返回查询结果对象
     */
    E findOne(E t);

    /**
     * 通过条件查询更新数据，会更新符合条件的所有匹配数据
     *
     * @param query  查询Query对象
     * @param update 更新条件
     */
    void updateMulti(Query query, Update update);

    /**
     * 通过条件查询更新数据,只会更新匹配条件的第一条数据
     *
     * @param query  查询Query对象
     * @param update 更新条件
     */
    void updateFirst(Query query, Update update);

    /**
     * 通过ID获取记录
     *
     * @param id ID
     * @return 符合条件的对象
     */
    E findById(ID id);

    /**
     * 通过ID获取记录,并且指定了集合名(表的意思)
     *
     * @param id             ID
     * @param collectionName 集合名
     * @return 符合条件的对象
     */
    E findById(ID id, String collectionName);

    /**
     * 通过条件查询,查询分页结果
     *
     * @param page  分页对象
     * @param query 查询query对象
     * @return 返回分页对象
     */
    Page<E> findPage(Page<E> page, Query query);
    Page<E> findPage(Page<E> page, Query query, String collectionName);

    Page<E> findPageByCondition(Page<E> page, E t);
    Page<E> findPageByCondition(Page<E> page, E t, String collectionName);

    /**
     * 求数据总和
     *
     * @param query 查询query对象
     * @return 返回符合条件的条数
     */
    long count(Query query);
    long count(Query query, String collectionName);

    /**
     * 根据ID找到文档然后替换
     *
     * @param id     ID
     * @param entity 需要替换的实体文档
     * @return 返回原始文档
     */
    E findAndReplace(ID id, E entity);

    /**
     * 根据条件找到文档然后替换
     *
     * @param query  查询query对象
     * @param entity 需要替换的实体文档
     * @return 返回原始文档
     */
    E findAndReplace(Query query, E entity);

    /**
     * 批量操作，包括insert和update
     *
     * @param data 需要批量朝着的数据
     */
    void batchUpsert(List<E> data);

    /**
     * 批量新增或修改 （指适合与）
     * @param dataList
     */
    void addOrUpdate(List<E> dataList);

    /**
     * 获取MongoDB模板操作
     *
     * @return 返回Mongodb对象
     */
    MongoTemplate getMongoTemplate();

    default void setMongoTemplate(MongoTemplate mongoTemplate) {

    }

    default void setTargetClass(Class<?> targetClass) {

    }

    /**
     * 获取JSON转换配置
     * @return
     */
    JsonWriterSettings getJsonWriterSettings();




    /**
     * 查询Mongo分页数据
     * @param target
     * @param pageIndex
     * @param pageSize
     * @param query
     * @param orders
     * @param <T>
     * @return
     */
    <T> PageInfo<T> queryPage(Class<T> target, Integer pageIndex, Integer pageSize, Query query, Sort.Order... orders);

    /**
     * 查询Mongo分页数据
     * @param target
     * @param mongoTemplate
     * @param pageIndex
     * @param pageSize
     * @param query
     * @param orders
     * @param <T>
     * @return
     */
    <T> PageInfo<T> queryPage(Class<T> target, MongoTemplate mongoTemplate, Integer pageIndex, Integer pageSize, Query query, Sort.Order... orders);

    /**
     * 查询Mongo分页数据
     * @param target
     * @param pageable
     * @param query
     * @param orders
     * @param <T>
     * @return
     */
    <T> PageInfo<T> queryPage(Class<T> target, Pageable pageable, Query query, Sort.Order... orders);

    /**
     * 查询Mongo分页数据
     * @param target
     * @param mongoTemplate
     * @param pageable
     * @param query
     * @param orders
     * @param <T>
     * @return
     */
    <T> PageInfo<T> queryPage(Class<T> target, MongoTemplate mongoTemplate,Pageable pageable, Query query, Sort.Order... orders);

    /**
     * 判断数据是否存在通过query
     * @param query
     * @return
     */
    Boolean isExists(Query query);

    /**
     * 判断数据是否存在通过数据唯一标识
     * @param id
     * @return
     */
    Boolean isExists(ID id);
}
